//! 表达式解析核心类型和常量定义

use std::cell::RefCell;
use std::rc::Rc;

/// 表达式类型标志位组合
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ExprType(u32);

impl ExprType {
    /// 基础类型掩码 (0x0000001F)
    pub const TYPE_MASK: u32 = 0x0000001F;
    
    /// 纯函数标记位 (0x00000020)
    pub const FLAG_PURE: u32 = 0x00000020;

    /// 基础表达式类型
    pub const VARIABLE: ExprType = ExprType(0);
    pub const FUNCTION0: ExprType = ExprType(8);
    pub const FUNCTION1: ExprType = ExprType(9);
    pub const FUNCTION2: ExprType = ExprType(10);
    pub const FUNCTION3: ExprType = ExprType(11);
    pub const FUNCTION4: ExprType = ExprType(12);
    pub const FUNCTION5: ExprType = ExprType(13);
    pub const FUNCTION6: ExprType = ExprType(14);
    pub const FUNCTION7: ExprType = ExprType(15);
    pub const CLOSURE0: ExprType = ExprType(16);
    pub const CLOSURE1: ExprType = ExprType(17);
    pub const CLOSURE2: ExprType = ExprType(18);
    pub const CLOSURE3: ExprType = ExprType(19);
    pub const CLOSURE4: ExprType = ExprType(20);
    pub const CLOSURE5: ExprType = ExprType(21);
    pub const CLOSURE6: ExprType = ExprType(22);
    pub const CLOSURE7: ExprType = ExprType(23);

    /// 检查是否为纯函数
    pub fn is_pure(self) -> bool {
        (self.0 & Self::FLAG_PURE) != 0
    }

    /// 获取函数参数数量
    pub fn arity(self) -> u32 {
        if self.is_function() || self.is_closure() {
            self.0 & 0x07
        } else {
            0
        }
    }

    /// 判断是否为函数类型
    pub fn is_function(self) -> bool {
        (self.0 & Self::FUNCTION0.0) != 0
    }

    /// 判断是否为闭包类型
    pub fn is_closure(self) -> bool {
        (self.0 & Self::CLOSURE0.0) != 0
    }
}

/// 表达式节点数据结构
#[derive(Debug)]
pub struct Expr {
    pub expr_type: ExprType,
    pub data: ExprData,
    pub parameters: Vec<Rc<RefCell<Expr>>>,
}

/// 表达式数据承载类型
#[derive(Debug)]
pub enum ExprData {
    Value(f64),
    Bound(*const f64),
    Function(*const std::ffi::c_void),
}
impl ExprData {
    pub fn as_function(&self) -> Option<*const std::ffi::c_void> {
        if let Self::Function(ptr) = self {
            Some(*ptr)
        } else {
            None
        }
    }
}
/// 变量/函数绑定描述结构
#[derive(Debug)]
pub struct Variable {
    pub name: &'static str,
    pub address: *const std::ffi::c_void,
    pub var_type: ExprType,
    pub context: *mut std::ffi::c_void,
}

/// 数学常数函数实现
pub fn pi() -> f64 { std::f64::consts::PI }
pub fn e() -> f64 { std::f64::consts::E }


/// 词法分析器标记类型常量
#[allow(non_upper_case_globals)]
pub const TOK_NULL: u32 = ExprType::CLOSURE7.0 + 1;
pub const TOK_ERROR: u32 = TOK_NULL + 1;
pub const TOK_END: u32 = TOK_ERROR + 1;
pub const TOK_SEP: u32 = TOK_END + 1;
pub const TOK_OPEN: u32 = TOK_SEP + 1;
pub const TOK_CLOSE: u32 = TOK_OPEN + 1;
pub const TOK_NUMBER: u32 = TOK_CLOSE + 1;
pub const TOK_VARIABLE: u32 = TOK_NUMBER + 1;
pub const TOK_INFIX: u32 = TOK_VARIABLE + 1;

/// 解析器状态管理结构
///
/// 记录表达式解析过程中的扫描位置、当前节点类型、数据承载、上下文及变量查找表信息
#[derive(Debug)]
pub struct State {
    /// 表达式字符串起始指针（原始字节形式）
    pub start: *const u8,
    /// 当前解析位置指针（原始字节形式）
    pub next: *const u8,
    /// 当前表达式节点类型标识
    pub expr_type: ExprType,
    /// 当前节点数据承载（替代C联合体）
    pub data: ExprData,
    /// 运行时上下文指针
    pub context: *mut std::ffi::c_void,
    /// 变量查找表起始地址
    pub lookup: *const Variable,
    /// 变量查找表有效条目数
    pub lookup_len: usize,
}

/// 在变量查找表中查找指定名称的变量
/// 
/// # 参数
/// - s: 解析器状态引用
/// - name: 要查找的变量名称字节切片
/// - len: 期望匹配的字节长度
/// 
/// # 返回
/// 找到的变量引用或None
pub unsafe fn find_lookup(s: &State, name: &[u8], len: usize) -> Option<&'static Variable> {
    if s.lookup.is_null() {
        return None;
    }

    let var_ptr = s.lookup as *const Variable;
    (0..s.lookup_len)
        .find_map(|i| {
            let var = &*var_ptr.add(i);
            let var_name = var.name.as_bytes();
            (var_name.len() == len && var_name.starts_with(&name[..len])).then_some(var)
        })
}

impl Expr {
    /// 递归打印表达式树结构
    ///
    /// # Parameters
    /// - `depth`: 当前递归深度，用于缩进控制
    fn print_node(&self, depth: usize) {
        let indent = " ".repeat(depth);
        print!("{}", indent);

        match &self.data {
            ExprData::Value(v) => println!("{}", v),
            ExprData::Bound(p) => println!("bound {:p}", p),
            ExprData::Function(_) => {
                if self.expr_type.is_function() || self.expr_type.is_closure() {
                    let arity = self.expr_type.arity() as usize;
                    print!("f{}", arity);
                    
                    // 打印参数指针地址
                    self.parameters[0..arity].iter().for_each(|p| {
                        print!(" {:p}", Rc::as_ptr(p));
                    });
                    println!();

                    // 递归打印子节点
                    self.parameters[0..arity].iter().for_each(|p| {
                        p.borrow().print_node(depth + 1);
                    });
                }
            }
        }
    }

    /// 公开的打印方法，初始化递归打印过程
    pub fn print(&self) {
        self.print_node(0);
    }
}


/// 表达式解析器实现模块

// 基本数学运算函数
#[inline]
pub extern "C" fn add(a: f64, b: f64) -> f64 { a + b }
#[inline]
pub extern "C" fn sub(a: f64, b: f64) -> f64 { a - b }
#[inline]
pub extern "C" fn mul(a: f64, b: f64) -> f64 { a * b }
#[inline]
pub extern "C" fn divide(a: f64, b: f64) -> f64 { a / b }
#[inline]
#[inline]
pub extern "C" fn negate(a: f64) -> f64 { -a }
#[inline]
pub extern "C" fn comma(a: f64, b: f64) -> f64 { b }
#[inline]
pub extern "C" fn pow(a: f64, b: f64) -> f64 { a.powf(b) }
#[inline]
pub extern "C" fn fmod(a: f64, b: f64) -> f64 { a % b }

unsafe fn parse_number(end: &mut *const u8) -> ExprData {
    let mut start = *end;
    let mut has_dot = false;
    while (*start).is_ascii_digit() || *start == b'.' {
        if *start == b'.' {
            if has_dot { break; }
            has_dot = true;
        }
        start = start.add(1);
    }
    let slice = std::slice::from_raw_parts(*end, start.offset_from(*end) as usize);
    let num_str = std::str::from_utf8_unchecked(slice);
    *end = start;
    ExprData::Value(num_str.parse().unwrap_or(0.0))
}

fn new_expr(
    expr_type: ExprType,
    function: *const std::ffi::c_void,
    params: Vec<Rc<RefCell<Expr>>>,
) -> Option<Rc<RefCell<Expr>>> {
    Some(Rc::new(RefCell::new(Expr {
        expr_type,
        data: ExprData::Function(function),
        parameters: params,
    })))
}
macro_rules! build_binary_expr {
    ($s:expr, $prev:expr, $func:ident, $next_fn:ident) => {{
        let next = $next_fn($s)?;
        new_expr(
            ExprType(ExprType::FUNCTION2.0 | ExprType::FLAG_PURE),
            $func as *const _,
            vec![$prev, next],
        )
    }};
}


fn power(s: &mut State) -> Option<Rc<RefCell<Expr>>> {
    let mut sign = 1;
    while s.expr_type.0 == TOK_INFIX {
        if let ExprData::Function(f) = s.data {
            if f == sub as *const _ {
                sign *= -1;
            }
            unsafe { next_token(s)? };
        } else {
            break;
        }
    }

    let base = base(s)?;
    if sign == 1 {
        Some(base)
    } else {
        new_expr(
            ExprType(ExprType::FUNCTION1.0 | ExprType::FLAG_PURE),
            negate as *const _,
            vec![base],
        )
    }
}
fn list(s: &mut State) -> Option<Rc<RefCell<Expr>>> {
    let mut ret = expr(s)?;
    while s.expr_type.0 == TOK_SEP {
        unsafe { next_token(s)? };
        ret = build_binary_expr!(s, ret, comma, expr)?;
    }
    Some(ret)
}

fn factor(s: &mut State) -> Option<Rc<RefCell<Expr>>> {
    let mut ret = power(s)?;
    while s.expr_type.0 == TOK_INFIX {
        if let ExprData::Function(f) = s.data {
            if f != pow as *const _ {
                break;
            }
            unsafe { next_token(s)? };
            ret = build_binary_expr!(s, ret, pow, power)?;
        }
    }
    Some(ret)
}

fn term(s: &mut State) -> Option<Rc<RefCell<Expr>>> {
    let mut ret = factor(s)?;
    while s.expr_type.0 == TOK_INFIX {
        let func = if let ExprData::Function(f) = s.data {
            match f as usize {
                x if x == mul as usize => mul,
                x if x == divide as usize => divide,
                x if x == fmod as usize => fmod,
                _ => break,
            }
        } else {
            break;
        };
        unsafe { next_token(s)? };
        ret = build_binary_expr!(s, ret, func, factor)?;
    }
    Some(ret)
}

fn expr(s: &mut State) -> Option<Rc<RefCell<Expr>>> {
    let mut ret = term(s)?;
    while s.expr_type.0 == TOK_INFIX {
        let func = if let ExprData::Function(f) = s.data {
            match f as usize {
                x if x == add as usize => add,
                x if x == sub as usize => sub,
                _ => break,
            }
        } else {
            break;
        };
        unsafe { next_token(s)? };
        ret = build_binary_expr!(s, ret, func, term)?;
    }
    Some(ret)
}

/// 内置函数查找
fn get_builtin_functions() -> &'static [Variable] {
    &[
        Variable {
            name: "pi",
            address: pi as *const _,
            var_type: ExprType::VARIABLE,
            context: std::ptr::null_mut(),
        },
        Variable {
            name: "e",
            address: e as *const _,
            var_type: ExprType::VARIABLE,
            context: std::ptr::null_mut(),
        },
    ]
}

fn find_builtin(name: &[u8], len: usize) -> Option<&'static Variable> {
    let functions = get_builtin_functions();
    functions
        .binary_search_by(|var| {
            let var_bytes = var.name.as_bytes();
            var_bytes[..len].cmp(&name[..len]).then(var_bytes.len().cmp(&len))
        })
        .ok()
        .map(|i| &functions[i])
}
unsafe fn next_token(s: &mut State) -> Option<()> {
    s.expr_type = ExprType(TOK_NULL);
    
    loop {
        if (*s.next).is_ascii_digit() || *s.next == b'.' {
            s.data = parse_number(&mut s.next);
            s.expr_type = ExprType(TOK_NUMBER);
            return Some(());
        }
        
        match *s.next {
            0 => {
                s.expr_type = ExprType(TOK_END);
                return Some(());
            }
            c if c.is_ascii_alphabetic() || c == b'_' => {
                let start = s.next;
                while (*s.next).is_ascii_alphanumeric() || *s.next == b'_' {
                    s.next = s.next.add(1);
                }
                
                if let Some(var) = find_builtin(std::slice::from_raw_parts(start, s.next.offset_from(start) as usize), (s.next.offset_from(start) as usize)) {
                let type_val = var.var_type.0 & ExprType::TYPE_MASK;
                match type_val {
                    x if x == ExprType::VARIABLE.0 => {
                        s.data = ExprData::Bound(var.address as *const _);
                        s.expr_type = ExprType(TOK_VARIABLE);
                    }
                    x if x >= ExprType::CLOSURE0.0 => {
                        s.context = var.context;
                        s.expr_type = ExprType(var.var_type.0);
                        s.data = ExprData::Function(var.address);
                    }
                    _ => {
                        s.expr_type = ExprType(var.var_type.0);
                        s.data = ExprData::Function(var.address);
                    }
                }
                    return Some(());
                }
            }
            c => {
                s.next = s.next.add(1);
                match c {
                    b'+' => s.data = ExprData::Function(add as _),
                    b'-' => s.data = ExprData::Function(sub as _),
                    b'*' => s.data = ExprData::Function(mul as _),
                    b'/' => s.data = ExprData::Function(divide as _),
                    b'^' => s.data = ExprData::Function(pow as _),
                    b'%' => s.data = ExprData::Function(fmod as _),
                    b'(' => s.expr_type = ExprType(TOK_OPEN),
                    b')' => s.expr_type = ExprType(TOK_CLOSE),
                    b',' => s.expr_type = ExprType(TOK_SEP),
                    b' ' | b'\t' | b'\n' | b'\r' => continue,
                    _ => {
                        s.expr_type = ExprType(TOK_ERROR);
                        return None;
                    }
                }
                if c.is_ascii_punctuation() && c != b'(' && c != b')' {
                    s.expr_type = ExprType(TOK_INFIX);
                }
                return Some(());
            }
        }
    }
}

fn base(s: &mut State) -> Option<Rc<RefCell<Expr>>> {
    let base_type = s.expr_type.0 & ExprType::TYPE_MASK;
    let ret = match base_type {
        TOK_NUMBER => {
            let value = if let ExprData::Value(v) = s.data { v } else { return None };
            unsafe { next_token(s)? };
            Some(Rc::new(RefCell::new(Expr {
                expr_type: ExprType(TOK_NUMBER),
                data: ExprData::Value(value),
                parameters: vec![],
            })))
        }

        TOK_VARIABLE => {
            let bound_ptr = if let ExprData::Bound(p) = s.data { p } else { return None };
            unsafe { next_token(s)? };
            Some(Rc::new(RefCell::new(Expr {
                expr_type: ExprType(TOK_VARIABLE),
                data: ExprData::Bound(bound_ptr),
                parameters: vec![],
            })))
        }

        x if x == ExprType::FUNCTION0.0 || x == ExprType::CLOSURE0.0 => {
            let expr_node = new_expr(s.expr_type, s.data.as_function()?, vec![])?;
            if expr_node.borrow().expr_type.is_closure() {
                expr_node.borrow_mut().parameters.push(Rc::new(RefCell::new(Expr {
                    expr_type: ExprType::VARIABLE,
                    data: ExprData::Bound(s.context as _),
                    parameters: vec![],
                })));
            }
            unsafe { next_token(s)? };
            if s.expr_type.0 == TOK_OPEN {
                unsafe { next_token(s)? };
                if s.expr_type.0 != TOK_CLOSE {
                    s.expr_type = ExprType(TOK_ERROR);
                    return None;
                }
                unsafe { next_token(s)? };
            }
            Some(expr_node)
        }

        x if x == ExprType::FUNCTION1.0 || x == ExprType::CLOSURE1.0 => {
            let expr_node = new_expr(s.expr_type, s.data.as_function()?, vec![])?;
            if expr_node.borrow().expr_type.is_closure() {
                expr_node.borrow_mut().parameters.push(Rc::new(RefCell::new(Expr {
                    expr_type: ExprType::VARIABLE,
                    data: ExprData::Bound(s.context as _),
                    parameters: vec![],
                })));
            }
            unsafe { next_token(s)? };
            let param = power(s)?;
            expr_node.borrow_mut().parameters.insert(0, param);
            Some(expr_node)
        }

        x if x >= ExprType::FUNCTION2.0 && x <= ExprType::CLOSURE7.0 => {
            let arity = ExprType(x).arity() as usize;
            let expr_node = new_expr(s.expr_type, s.data.as_function()?, vec![])?;
            
            if expr_node.borrow().expr_type.is_closure() {
                expr_node.borrow_mut().parameters.push(Rc::new(RefCell::new(Expr {
                    expr_type: ExprType::VARIABLE,
                    data: ExprData::Bound(s.context as _),
                    parameters: vec![],
                })));
            }
            unsafe { next_token(s)? };
            
            if s.expr_type.0 != TOK_OPEN {
                s.expr_type = ExprType(TOK_ERROR);
                return None;
            }
            
            for i in 0..arity {
                unsafe { next_token(s)? };
                let param = expr(s)?;
                expr_node.borrow_mut().parameters.insert(i, param);
                
                if s.expr_type.0 != TOK_SEP {
                    break;
                }
            }
            
            if s.expr_type.0 != TOK_CLOSE || expr_node.borrow().parameters.len() != arity {
                s.expr_type = ExprType(TOK_ERROR);
                return None;
            }
            unsafe { next_token(s)? };
            Some(expr_node)
        }

        TOK_OPEN => {
            unsafe { next_token(s)? };
            let expr = list(s)?;
            if s.expr_type.0 != TOK_CLOSE {
                s.expr_type = ExprType(TOK_ERROR);
                return None;
            }
            unsafe { next_token(s)? };
            Some(expr)
        }

        _ => {
            s.expr_type = ExprType(TOK_ERROR);
            None
        }
    };

    ret
}

/// 表达式求值实现
impl Expr {
    /// 递归求值表达式树
    /// 
    /// # 返回
    /// 计算结果或NaN
    pub fn eval(&self) -> f64 {
        match self.expr_type.0 & ExprType::TYPE_MASK {
            TOK_NUMBER => {
                if let ExprData::Value(v) = self.data {
                    v
                } else {
                    f64::NAN
                }
            }
            TOK_VARIABLE => {
                if let ExprData::Bound(p) = self.data {
                    unsafe { *p }
                } else {
                    f64::NAN
                }
            }
            _ => {
                let arity = self.expr_type.arity() as usize;
                let args: Vec<f64> = self.parameters[0..arity]
                    .iter()
                    .map(|p| p.borrow().eval())
                    .collect();

                match self.data {
                    ExprData::Function(f) => unsafe {
                        match arity {
                            0 => (std::mem::transmute::<_, fn() -> f64>(f))(),
                            1 => (std::mem::transmute::<_, fn(f64) -> f64>(f))(args[0]),
                            2 => (std::mem::transmute::<_, fn(f64, f64) -> f64>(f))(args[0], args[1]),
                            // ...其他参数数量处理
                            _ => f64::NAN,
                        }
                    },
                    _ => f64::NAN,
                }
            }
        }
    }

    /// 优化表达式树
    /// 
    /// 将纯函数且参数全为常量的子树转换为常量节点
    pub fn optimize(&mut self) {
        if self.expr_type.0 == TOK_NUMBER || self.expr_type.0 == TOK_VARIABLE {
            return;
        }

        if self.expr_type.is_pure() {
            let arity = self.expr_type.arity() as usize;
            let mut all_constant = true;

            for param in &mut self.parameters[0..arity] {
                param.borrow_mut().optimize();
                if param.borrow().expr_type.0 != TOK_NUMBER {
                    all_constant = false;
                }
            }

            if all_constant {
                let value = self.eval();
                self.expr_type = ExprType(TOK_NUMBER);
                self.data = ExprData::Value(value);
                self.parameters.clear();
            }
        }
    }
}

/// 编译表达式字符串为表达式树
/// 
/// # 参数
/// - expr: 表达式字符串
/// - vars: 变量查找表
/// 
/// # 返回
/// 解析结果及错误位置
pub fn te_compile(
    expr: &str,
    vars: &[Variable],
) -> Result<Rc<RefCell<Expr>>, usize> {
    let mut state = State {
        start: expr.as_ptr(),
        next: expr.as_ptr(),
        expr_type: ExprType(TOK_NULL),
        data: ExprData::Value(0.0),
        context: std::ptr::null_mut(),
        lookup: vars.as_ptr(),
        lookup_len: vars.len(),
    };

    unsafe { next_token(&mut state).ok_or_else(|| unsafe { state.next.offset_from(state.start) as usize })?; }
    let root = list(&mut state).ok_or_else(|| unsafe { state.next.offset_from(state.start) as usize })?;

    if state.expr_type.0 != TOK_END {
        let err_pos = unsafe { state.next.offset_from(state.start) } as usize;
        return Err(if err_pos == 0 { 1 } else { err_pos });
    }

    root.borrow_mut().optimize();
    Ok(root)
}

/// 解释执行表达式字符串
/// 
/// # 参数
/// - expr: 要计算的表达式字符串
/// 
/// # 返回
/// 计算结果
pub fn te_interp(expr: &str) -> f64 {
    te_compile(expr, &[])
        .map_or(f64::NAN, |n| n.borrow().eval())
}